import _ from 'underscore';
import { fromJS } from 'immutable';

import { Scope } from 'lib/scopeFactory';
import { restApi, restPostApi } from '../apis/core-util';

import { Columns } from './Constant.es6';

export default class AgentSettingFormXScope extends Scope {
  constructor(props) {
    super(props);

    this.dataSource = null;
    this.$state = {
      isProcessing: false,
      isEditing: false,
      store: {
        loading: true
      }
    }; // $state

    this.changes = {};

    this.dataApi = restApi({
      __url: `app/${ BlueWare.appId }/settings`
    });

    this.dataPostApi = restPostApi({
      __url: `app/${ BlueWare.appId }/settings`
    });
  } // constructor

  convertValue(value) {
    let convertedValue = value;

    if (value === '1') {
      convertedValue = true;
    } else if (value === '0') {
      convertedValue = false;
    }

    return convertedValue;
  } // convertValue

  getEditableColumns() {
    let { data } = this.$state.store
      , settings = data.getIn(['app', 'settings'])
                       .filter((v, k) => v && Columns.includes(k));

    return settings.keySeq();
  } // getEditableColumns

  $change_all_property({ value, changes }) {
    let convertedValue = this.convertValue(value)
      , { store } = this.$state;

    Columns.forEach(key => {
      store.data = store.data.setIn(['app', 'settings', key], convertedValue);
    });

    _.extend(this.changes, changes);

    this.emit();
  } // $change_all_property

  $change_column_property({ key, value, changes }) {
    let convertedValue = this.convertValue(value)
      , { store } = this.$state;

    store.data = store.data.setIn(['app', 'settings', key], convertedValue);

    _.extend(this.changes, changes);

    this.emit();
  } // $change_column_property

  $change_multi_property({ keys, value, changes }) {
    let convertedValue = this.convertValue(value)
      , { store } = this.$state
      , editableKeys = this.getEditableColumns();

    store.data
         .getIn(keys)
         .filter((v, k) => editableKeys.includes(k))
         .forEach((v, k) => {
           store.data = store.data.setIn(keys.concat(k), convertedValue);
         });

    _.extend(this.changes, changes);

    this.emit();
  } // $change_multi_property

  $change_property({ keys, value, changes }) {
    let convertedValue = this.convertValue(value);

    _.extend(this.changes, changes);

    this.$state.store.data = this.$state.store.data.setIn(keys, convertedValue);
    this.emit();
  } // $change_property

  $cancel() {
    this.$state.isEditing = false;
    this.$state.store = {
      data: this.dataSource
    };

    this.emit();
  } // $cancel

  $edit() {
    this.$state.isEditing = true;

    this.emit();
  } // $edit

  $save() {
    this.dataPostApi
        .append({
          changes: _.map(this.changes, v => v).join('|')
        })
        .fetch()
        .progress(() => {
          this.changes = {};
          this.$state.isProcessing = true;
          this.$state.isEditing = false;
          this.emit();
        })
        .fail(() => this.$reset_store())
        .done(data => {
          this.$state.isProcessing = false;

          this.dataSource = fromJS(data);
          this.$state.store = {
            data: this.dataSource
          };
        })
        .always(() => this.emit());
  } // $save

  $load() {
    this.dataApi
        .fetch()
        .progress(() => {
          this.$state.store = {
            loading: true
          };

          this.emit();
        })
        .fail(error => this.$state.store = { error })
        .done(data => {
          this.dataSource = fromJS(data);
          this.$state.store = {
            data: this.dataSource
          };
        })
        .always(() => this.emit());
  } // $load
}
